/**
 * Created on 12 avr. 08 by Sebastian Audet
 */
package gui2Dengine;

import java.awt.Point;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;

/**
 * This class uses the Java2D package's GeneralPath to define the paths that
 * make up a Hexagon.
 * 
 * <br>
 * <br>
 * A Hexagon is defined as:
 * <ul>
 * <li>A set of six points</li>
 * <li>A set of methods to return and rotate the Hexagon</li>
 * <li>A set of methods to return properties of the Hexagon, such as side
 * length, etc.</li>
 * <li>A GeneralPath that implements the Hexagon</li>
 * </ul>
 * 
 * @author Sebastian Audet
 * 
 */
public class Hexagon{

    private final static double SIXTY_DEG = Math.PI / 3;
    private final static double ONE_HUNDRED_TWENTY_DEG = 4 * (Math.PI / 6);
    private final static double ONE_DEGREE = Math.PI/180;
    private final static double defaultlength = 25;
    private Point2D.Double p1 = null;
    private Point2D.Double p2 = null;
    private Point2D.Double p3 = null;
    private Point2D.Double p4 = null;
    private Point2D.Double p5 = null;
    private Point2D.Double p6 = null;
    private Point2D.Double center = null;
    private GeneralPath hexagon = new GeneralPath();
    private double length = defaultlength;

    public Hexagon(Point p) {
	this(new Point2D.Double(p.getX(),p.getY()));
    }

    public Hexagon(Point2D.Double p) {
	this(p,defaultlength);
    }

    public Hexagon(Point2D.Float p) {
	this(new Point2D.Double(p.getX(),p.getY()));
    }

    public Hexagon(Point p, double length) {
	this(new Point2D.Double(p.getX(),p.getY()),length);
    }

    public Hexagon(Point2D.Double p, double length) {
	this(p,length,0);
    }

    public Hexagon(Point2D.Float p, double length) {
	this(new Point2D.Double(p.getX(),p.getY()),length);
    }

    public Hexagon(Point p, double length, double rotationangle) {
	this(new Point2D.Double(p.getX(),p.getY()),length,rotationangle);
    }

    /**
     * This is the implementing constructor, all other constructors call this one
     * <br><br>Creates a Hexagon by connecting the dots from the corner point
     * @param p The middle-left corner of the Hexagon
     * @param length The length of a hexagon side
     * @param rotationangle The angle of rotation to the right apply to the hexagon, rotating around the corner point
     */
    public Hexagon(Point2D.Double p, double length, double rotationangle) {
	this.length = length;
	p1 = p;
	center = getRadialPoint(p1, getRadiusDistance(), 0+rotationangle);
	p2 = getRadialPoint(p1, length, SIXTY_DEG+rotationangle);
	p3 = getRadialPoint(p2, length, rotationangle);
	p4 = getRadialPoint(p3, length, -SIXTY_DEG+rotationangle);
	p5 = getRadialPoint(p4, length, -ONE_HUNDRED_TWENTY_DEG+rotationangle);
	p6 = getRadialPoint(p5, length, Math.PI+rotationangle);
	hexagon.moveTo(p.x, p.y);
	hexagon.lineTo(p2.x, p2.y);
	hexagon.lineTo(p3.x, p3.y);
	hexagon.lineTo(p4.x, p4.y);
	hexagon.lineTo(p5.x, p5.y);
	hexagon.lineTo(p6.x, p6.y);
	hexagon.closePath();
    }

    public double getRadiusDistance() {
	return (length * Math.cos(SIXTY_DEG))+(length/2);
    }
    
    public double getBisectorDistance() {
	return 2*getRadiusDistance();
    }
    
    public double getTrapBaseDistance() {
	return (2*length*Math.sin(SIXTY_DEG))+length;
    }
    
    public double getLength()
    {
	return length;
    }

    public static double getRadiusDistance(double length) {
	return (length * Math.cos(SIXTY_DEG))+(length/2);
    }
    
    public static double getBisectorDistance(double length) {
	return 2*getRadiusDistance(length);
    }
    
    public static double getTriSideLength(double length) {
	return length*Math.sin(SIXTY_DEG);
    }
    
    public Hexagon(Point2D.Float p, double length, double rotationangle) {
	this(new Point2D.Double(p.getX(),p.getY()),length,rotationangle);
    }

    //Was Unused, initially had use
    /*private static Line2D.Double getRadialLine(Point p, double length,
	    double degree) {
	return new Line2D.Double(p, getRadialPoint(new Point2D.Double(p.getX(),p.getY()), length, degree));
    }*/

    private static Point2D.Double getRadialPoint(Point2D.Double p, double length,
	    double degree) {
	return new Point2D.Double((p.getX() + (length * Math.cos(degree))), (p.getY() + (length * Math.sin(degree))));
    }

    
    public static double getRadians(double degree) {
	return ONE_DEGREE*degree;
    }
    
    public GeneralPath getHexagon() {
	return hexagon;
    }
    
    public Point2D.Double getCenter()
    {
	return center;
    }
    
    public static Point2D.Double getCenter(Point2D.Double p,double length,double rotationangle)
    {
	return getRadialPoint(p, getRadiusDistance(length), 0+rotationangle);
    }
    /*public static void main(String[] args) {
	JFrame frame = new JFrame() {
	    /**
	     * long serialVersionUID
	     */
	    /*private static final long serialVersionUID = 1L;

	    public void paint(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;
		g2.setBackground(Color.red);
		g2.setColor(Color.green);
		g2.setPaint(Color.blue);
		g2.setStroke(new BasicStroke());
		
		//HexGrid Code
		ArrayList<GeneralPath> hexagons = new ArrayList<GeneralPath>();
		Point p = new Point(getX(), getY() + 40);
		int length = 50;
		boolean switcher = true;
		for (int i = 0; i <= 14; i++) {
		    for (int j = 0; j <= 4; j++) {
			if (switcher) {
			    hexagons.add(new Hexagon(new Point2D.Double(p.x + j
				    * (getBisectorDistance(length) + length),
				    p.y + (i * getTriSideLength(length))),
				    length).getHexagon());
			} else {
			    hexagons.add(new Hexagon(new Point2D.Double(p.x
				    + getRadiusDistance(length) + (length / 2)
				    + j
				    * (getBisectorDistance(length) + length),
				    p.y + (i * getTriSideLength(length))),
				    length).getHexagon());
			}
		    }
		    switcher = !switcher;
		} // End HexGrid Code
		
		switcher = true;
		for (GeneralPath path : hexagons) {
		    g2.draw(path);
		    if (switcher) {
			g2.setPaint(Color.RED);
		    } else {
			g2.setPaint(Color.BLUE);
		    }
		    g2.fill(path);
		    switcher = !switcher;
		}
	    }
	};
	frame.setSize(800, 800);
	frame.setVisible(true);
    }*/

}
